﻿using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Zero.UControl.Component
{
    /// <summary>
    /// RaderChart.xaml 的交互逻辑
    /// </summary>
    public partial class RaderChart : UserControl
    {
        public ObservableCollection<RaderSeriesModel> ItemsSources
        {
            get { return (ObservableCollection<RaderSeriesModel>)GetValue(ItemsSourcesProperty); }
            set
            {
                SetValue(ItemsSourcesProperty, value);
            }
        }
        public static readonly DependencyProperty ItemsSourcesProperty =
        DependencyProperty.Register(
        "ItemsSources",
        typeof(ObservableCollection<RaderSeriesModel>),
            typeof(RaderChart),
            new PropertyMetadata(null, new PropertyChangedCallback(OnPropertyChanged)));

        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue == null) return;
            (e.NewValue as ObservableCollection<RaderSeriesModel>).CollectionChanged += (se, ev) =>
                    {
                        (d as RaderChart).Refresh();
                    };
        }

        public string LabelFormat { get; set; } = "$Header_$Value";

        private List<RaderPoint> raderPoints = new List<RaderPoint>();
        private List<Color> colorList = new List<Color>();
        private Random random = new Random();
        public RaderChart()
        {
            InitializeComponent();
            this.SizeChanged += RaderChart_SizeChanged;

            #region 颜色表
            colorList.Add((Color)ColorConverter.ConvertFromString("#00FF00"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#FF69B4"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#FFDEAD"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#7FFFD4"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#FFD700"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#00FFFF"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#00BFFF"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#8A2BE2"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#0000CD"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#7B68EE"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#778899"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#F4A460"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#DC143C"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#FF1493"));
            colorList.Add((Color)ColorConverter.ConvertFromString("#7FFF00"));
            #endregion
        }

        private void UserControl_MouseMove(object sender, MouseEventArgs e)
        {
            Point point = e.GetPosition(this);
            RaderPoint nearstPoint = null;
            double minLen = 100;
            for (int i = 0; i < raderPoints.Count; i++)
            {
                Vector vector = point - raderPoints[i].Position;
                if (vector.Length < minLen && vector.Length < 30)
                {
                    minLen = vector.Length;
                    nearstPoint = raderPoints[i];
                }
            }

            if (nearstPoint != null)
            {
                circle.Fill = nearstPoint.Fill;
                header.Text = LabelFormat.Replace("$Header", nearstPoint.Model.Header)
                                         .Replace("$Value", nearstPoint.Model.Value.ToString());
                popBox.HorizontalOffset = point.X + 10;
                popBox.VerticalOffset = point.Y + 10;
                popBox.IsOpen = true;
            }
            else
            {
                popBox.IsOpen = false;
            }
        }

        private void RaderChart_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.Refresh();
        }

        private void Refresh()
        {
            if (ItemsSources.Count == 0) return;
            int threshold = (int)ItemsSources.Max(t => t.Value) + 30;

            List<Color> colors = new List<Color>();
            while (colors.Count < ItemsSources.Count)
            {
                Color color = colorList[random.Next(colorList.Count)];
                if (!colors.Contains(color))
                    colors.Add(color);
            }

            this.mainCanvas.Children.Clear();
            this.p1.Points.Clear();
            this.p2.Points.Clear();
            this.p3.Points.Clear();
            this.p4.Points.Clear();
            this.p5.Points.Clear();

            // 设置区域大小
            double size = Math.Min(RenderSize.Width, RenderSize.Height);
            this.LayoutRoot.Width = size;
            this.LayoutRoot.Height = size;
            double raduis = size / 2;
            double angleToRad = Math.PI / 180;

            double step = 360.0 / ItemsSources.Count;
            for (int i = 0; i < ItemsSources.Count; i++)
            {
                p1.Points.Add(new Point(
                raduis + (raduis - 20) * Math.Cos((step * i - 90) * angleToRad),
                raduis + (raduis - 20) * Math.Sin((step * i - 90) * angleToRad)
                ));
                p2.Points.Add(new Point(
                raduis + (raduis - 20) * Math.Cos((step * i - 90) * angleToRad) * 0.25,
                raduis + (raduis - 20) * Math.Sin((step * i - 90) * angleToRad) * 0.25
                ));
                p3.Points.Add(new Point(
                raduis + (raduis - 20) * Math.Cos((step * i - 90) * angleToRad) * 0.5,
                raduis + (raduis - 20) * Math.Sin((step * i - 90) * angleToRad) * 0.5
                ));
                p4.Points.Add(new Point(
                raduis + (raduis - 20) * Math.Cos((step * i - 90) * angleToRad) * 0.75,
                raduis + (raduis - 20) * Math.Sin((step * i - 90) * angleToRad) * 0.75
                ));

                double posX = raduis + (raduis - 20) * Math.Cos((step * i - 90) * angleToRad) * ItemsSources[i].Value / threshold;
                double posY = raduis + (raduis - 20) * Math.Sin((step * i - 90) * angleToRad) * ItemsSources[i].Value / threshold;
                p5.Points.Add(new Point(posX, posY));

                Line line = new Line();
                line.Stroke = new SolidColorBrush(Color.FromArgb(80, 255, 255, 255));
                line.StrokeThickness = 1;
                line.X1 = raduis;
                line.Y1 = raduis;
                line.X2 = raduis + (raduis - 20) * Math.Cos((step * i - 90) * angleToRad);
                line.Y2 = raduis + (raduis - 20) * Math.Sin((step * i - 90) * angleToRad);
                this.mainCanvas.Children.Add(line);

                Ellipse ellipse = new Ellipse();
                ellipse.Width = 6;
                ellipse.Height = 6;
                ellipse.Fill = new SolidColorBrush(colors[i]);
                ellipse.SetValue(Canvas.LeftProperty, posX - 3);
                ellipse.SetValue(Canvas.TopProperty, posY - 3);
                this.mainCanvas.Children.Add(ellipse);
                raderPoints.Add(new RaderPoint() { Model = ItemsSources[i], Element = ellipse, Position = new Point(posX, posY), Fill = new SolidColorBrush(colors[i]) });

                TextBlock text = new TextBlock();
                text.Width = 60;
                text.FontSize = 10;
                text.TextAlignment = TextAlignment.Center;
                text.Text = ItemsSources[i].Header;
                text.Foreground = new SolidColorBrush(Color.FromArgb(100, 255, 255, 255));
                text.SetValue(Canvas.LeftProperty, raduis + (raduis - 10) * Math.Cos((step * i - 90) * angleToRad) - 30);
                text.SetValue(Canvas.TopProperty, raduis + (raduis - 10) * Math.Sin((step * i - 90) * angleToRad) - 7);
                this.mainCanvas.Children.Add(text);
            }
        }
    }

    public class RaderSeriesModel
    {
        public string Header { get; set; }
        public double Value { get; set; }
    }

    internal class RaderPoint
    {
        public RaderSeriesModel Model { get; set; }
        public Ellipse Element { get; set; }
        public Point Position { get; set; }
        public Brush Fill { get; set; } = new SolidColorBrush(Colors.LightCyan); // 默认颜色
    }
}
